# $Id: log.py 57e426c1dd62 2012/08/25 23:49:38 pgurumur $
# Copyright (c) 2009 Prabhu Gurumurthy  <pgurumur@gmail.com>
# 
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#

import logging
import logging.handlers
import StringIO
import sys

class LogError(Exception):
   pass

class Log(object):
   def __init__(self, Name, Level = logging.DEBUG):
      self._level = None
      self._handler = None
      self._name = None

      if Level is not None:
         self._level = Level
      else:
         self._level = logging.DEBUG

      if Name:
         self._name = self._tostr(Name)
      else:
         self._name = self._tostr(self.__class__.__name__)

      self._logger = logging.getLogger(self._name)
      self._logger.setLevel(Level)
      self._formatter = logging.Formatter(
            "%(asctime)s - %(name)s - %(levelname)s - %(message)s")

   def _tostr(self, Message):
      message = None
      if Message:
         if not isinstance(Message, str):
            message = str(Message).encode('utf-8')
         else:
            message = Message.encode('utf-8')

      return message

   def __call__(self, fmt, *args):
      newstr = StringIO.StringIO()
      newstr.write(fmt %args)
      logstr = str(newstr.getvalue()).encode('utf-8')
      newstr.close()

      self.info(logstr)

   def __str__(self):
      return self._name

   def __repr__(self):
      return repr(str(self))

   def __unicode__(self):
      return unicode(str(self))

   def info(self, Message):
      self._logger.info(self._tostr(Message))

   def debug(self, Message):
      self._logger.debug(self._tostr(Message))

   def warn(self, Message):
      self._logger.warn(self._tostr(Message))

   def error(self, Message):
      self._logger.error(self._tostr(Message))

   def critical(self, Message):
      self._logger.critical(self._tostr(Message))

class StreamLog(Log):
   def __init__(self, Name = None, stream = None):
      super(StreamLog, self).__init__(Name)
      self._stream = None
      if stream:
         self._stream = stream

      if self._stream:
         self._handler = logging.StreamHandler(self._stream)
      else:
         self._handler = logging.StreamHandler()

      self._handler.setLevel(self._level)
      self._handler.setFormatter(self._formatter)
      self._logger.addHandler(self._handler)

   @property
   def stream(self):
      return self._stream

class SysLog(Log):
   def __init__(self, Name = None, Host = "localhost", Port = 514):
      super(SysLog, self).__init__(Name)
      self._port = 0
      try:
         if Port:
            self._port = int(Port)
      except ValueError, message:
         raise LogError, message

      self._handler = logging.handlers.SysLogHandler((Host, Port),
            logging.handlers.SysLogHandler.LOG_USER)
      self._handler.setFormatter(self._formatter)
      self._handler.setLevel(self._level)
      self._logger.addHandler(self._handler)

   def __int__(self):
      return int(self._port)

class FileLog(Log):
   def __init__(self, *args, **kwargs):
      if len(args):
         super(FileLog, self).__init__(args[0])
      else:
         super(FileLog, self).__init__(None)

      self._file = None
      self._rotate = False
      self._count = None

      if "filename" in kwargs:
         self._file = kwargs["filename"]

      if "rotate" in kwargs:
         if kwargs["rotate"] is not None:
            self._rotate = bool(kwargs["rotate"])

      if "count" in kwargs:
         try:
            self._count = int(kwargs["count"])
         except ValueError, message:
            raise LogError, message

      if self._file:
         if self._rotate:
            if self._count:
               self._handler = logging.handlers.RotatingFileHandler(
                     self._file, backupCount = self._count)
            else:
               raise LogError, "No count given to rotating file handler"
         else:
            self._handler = logging.FileHandler(self._file)
      else:
         raise LogError, "No filename defined!"


      if self._handler:
         self._handler.setFormatter(self._formatter)
         self._logger.addHandler(self._handler)

class NullLog(StreamLog):
   def __init__(self, Name):
      super(NullLog, self).__init__(Name, stream = StringIO.StringIO())
